#ifndef _MP4_H
#define _MP4_H
#include <sys/types.h>
#include "list.h"

#define BOX_HLEN 8
#define FULLBOX_HLEN 12
union box_type{
	u_int32_t itype;
	char type[5];
} ;
struct boxhdr {
	unsigned int offset;
	u_int32_t size;
	union box_type type;
};

struct fullboxhdr {
	unsigned int offset;
	u_int32_t size;
	union box_type type;
	unsigned char ver;
	unsigned int flags;
};



/* stts box */
struct stts_entry {
	u_int32_t count;
	u_int32_t delta;
	struct list_head list;
};
struct stts {
	struct fullboxhdr hdr;
	u_int32_t count;
	struct list_head entry; 
};

/* ctts box */
struct ctts_entry {
	u_int32_t count;
	u_int32_t offset;
	struct list_head list;

};

struct ctts {
	struct fullboxhdr hdr;
	u_int32_t count;
	struct list_head entry; 
};

/* stsc box */
struct stsc_entry {
	u_int32_t first_chunk;
	u_int32_t sample_per_chunk;
	u_int32_t sample_desc_index;
	struct list_head list;
};

struct stsc {
	struct fullboxhdr hdr;
	u_int32_t count;
	struct list_head entry; 
};


/* stsz box */
struct stsz_entry { 
	u_int32_t size;
	struct list_head list;
};

struct stsz {
	struct fullboxhdr hdr;
	u_int32_t sample_size;
	u_int32_t sample_count;
	struct list_head entry;
};

/* stco box */
struct stco_entry {
	u_int32_t offset;
	struct list_head list;
};
struct stco {
	struct fullboxhdr hdr;
	u_int32_t count;
	struct list_head entry;
};


/* stss box */
struct stss_entry {
	u_int32_t sample_num;
	struct list_head list;
};

struct stss {
	struct fullboxhdr hdr;
	u_int32_t count;
	struct list_head entry;
};

struct stbl {
	struct boxhdr hdr;
	struct stts stts;
	struct ctts ctts;
	struct stsc stsc;
	struct stsz stsz;
	struct stco stco;
	struct stss stss;
};

struct minf {
	struct boxhdr hdr;
	struct stbl stbl;
};

struct hdlr {
	struct fullboxhdr hdr;
	u_int32_t pre_define;
	u_int32_t handler_type;
};

struct mdhd {
	struct fullboxhdr hdr;
	union {
		struct {
			u_int64_t create_time;
			u_int64_t mod_time;
			u_int32_t timescale;
			u_int64_t duration;
		}l;
		struct {
			u_int32_t create_time;
			u_int32_t mod_time;
			u_int32_t timescale;
			u_int32_t duration;
		}s;
	} u;
};

struct mdia {
	struct boxhdr hdr;
	struct mdhd mdhd;
	struct hdlr hdlr;
	struct minf minf;
};

struct tkhd {
	struct fullboxhdr hdr;
	union {
		struct {
			u_int64_t create_time;
			u_int64_t mod_time;
			u_int32_t track_id;
			u_int64_t duration;
		}l;
		struct {
			u_int32_t create_time;
			u_int32_t mod_time;
			u_int32_t track_id;
			u_int32_t duration;
		}s;
	} u;
};

struct trak {
	struct boxhdr hdr;
	struct tkhd tkhd;
	struct mdia mdia;
	struct list_head list;
};


struct mvhd {
	struct fullboxhdr hdr;
	union {
		struct {
			u_int64_t create_time;
			u_int64_t mod_time;
			u_int32_t timescale;
			u_int64_t duration;
		}l;
		struct {
			u_int32_t create_time;
			u_int32_t mod_time;
			u_int32_t timescale;
			u_int32_t duration;
		}s;
	} u;
};

struct moov {
	struct boxhdr hdr;
	struct mvhd mvhd;
	struct list_head entry;
	int count;
};

struct mdat {
	struct boxhdr hdr;
	unsigned int lowest_offset;
};

struct mp4 { /* has no header */
	struct moov moov;
	struct mdat mdat;
};

#endif
